package es.uned.etsii.si3.taller;

import com.j256.ormlite.field.DataType;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import java.sql.SQLException;
import java.util.List;

/**
 * El tipo "Empleado" almacena datos personales sobre el empleado.
 * Para todo lo demás (id para facturación, etc.) se usará el tipo "Usuario"
 **/
@DatabaseTable(tableName = "empleados")
public
class Empleado extends Persistente {
	public static final String ID_FIELD_NAME = "id";
	public static final String ID_USUARIO_FIELD_NAME = "id_usuario";
	public static final String DNI_FIELD_NAME = "dni";
	public static final String NOMBRE_FIELD_NAME = "nombre";
	public static final String APELLIDOS_FIELD_NAME = "apellidos";
	public static final String CATEGORIA_FIELD_NAME = "categoria";
	public static final String ROL_ADMINISTRADOR = "administrador";
	public static final String ROL_JEFESECCION = "jefeseccion";
	public static final String ROL_JEFETALLER = "jefetaller";
	public static final String ROL_MECANICO = "mecanico";
	
	/**
	 * Enum con los distintos tipos de sección existentes
	 *
	 */
	public enum Categoria {
		NO_VALIDA(-1),
		ADMINISTRADOR(0), JEFE_TALLER(1), JEFE_SECCION(2), MECANICO(3);
		
		private static String[] descriptores = {
			"----------",
			"Administrador",
			"Jefe de taller",
			"Jefe de sección",
			"Mecánico"
			};

		private int index;
		private Categoria(int index) {
			this.index = index;
		}
		
		public int getIndex() {
			return index;
		}
		
		public String getName() {
			return name();
		}
		
		public String getDescriptor() {
			return descriptores[getIndex() + 1];
		}
	};

	@DatabaseField(generatedId = true, columnName = ID_FIELD_NAME)
	int id;
	@DatabaseField(foreign = true, maxForeignAutoRefreshLevel=5, foreignAutoRefresh=true, columnName = ID_USUARIO_FIELD_NAME)
	Usuario usuario;
	@DatabaseField(width = 9, index = true, columnName = DNI_FIELD_NAME)
	String dni;
	@DatabaseField(width = 30, columnName = NOMBRE_FIELD_NAME)
	String nombre;
	@DatabaseField(width = 60, columnName = APELLIDOS_FIELD_NAME)
	String apellidos;
	@DatabaseField(width = 20)
	String telefono;
	@DatabaseField(width = 20)
	String cuentaCorriente;
	@DatabaseField(dataType = DataType.ENUM_INTEGER, columnName = CATEGORIA_FIELD_NAME)
	Categoria categoria;

	/**
	 * Factoría para crear nuevos empleados partiendo de un conjunto de datos,
	 * al tiempo que se crear el objeto en la base de datos
	 *
	 * @param  usuario         usuario al que está asociado esta información
	 * @param  nombre          nombre del empleado
	 * @param  apellidos       apellido(s) del empleado
	 * @param  dni             documento de identidad del empleado (9 dígitos)
	 * @param  telefono
	 * @param  cuentaCorriente 20 dígitos de la cuenta bancaria
	 * @param  categoria       categoría profesional, tomada de la enumeración
	 * @return          un nuevo objeto, ya guardado en la base de datos
	 */
	public
	static Empleado crear(Usuario usuario, String nombre, String apellidos,
			String dni, String telefono, String cuentaCorriente,
			Categoria categoria) throws SQLException
	{
		Empleado empleado = new Empleado();

		empleado.setUsuario(usuario);
		empleado.setNombre(nombre);
		empleado.setApellidos(apellidos);
		empleado.setDni(dni);
		empleado.setTelefono(telefono);
		empleado.setCuentaCorriente(cuentaCorriente);
		empleado.setCategoria(categoria);
		getClassDao(Empleado.class).create(empleado);

		return empleado;
	}

	/**
	 * Factoría para crear nuevos empleados partiendo de un objeto
	 * empleado ya existente.
	 *
	 * @param  empleado objeto con todos los datos deseados rellenos (excepto,
	 *                  quizá el id)
	 * @return          un nuevo objeto, ya guardado en la base de datos,
	 *                  así que tendrá ID
	 * 
	 * @throws SQLException
	 */
	public static Empleado crear(Empleado empleado) throws SQLException {
		getClassDao(Empleado.class).create(empleado);
		
		return empleado;
	}

	/**
	 * Permite obtener el empleado que corresponde a un usuario dado
	 * 
	 * @param usuario objeto de tipo usuario del que se quiere averiguar su empleado
	 * @return empleado que corresponde al usuario
	 * @throws SQLException
	 */
	public
	static Empleado buscarPorUsuario(Usuario usuario) throws SQLException {
		List<Empleado> empleados = getClassDao(Empleado.class).queryForEq(ID_USUARIO_FIELD_NAME, usuario);

		if (empleados.size() == 0)
			return null;

		if (empleados.size() > 1) {
			// TODO: No debería suceder. ¿Qué hacer?
		}

		return empleados.get(0);
	}

	public
	Empleado() {
		// ORM Lite necesita un constructor por defecto
	}

	/**
	 * Getters y setters
	 * 
	 */
	public int       getId()              { return id; }
	public Usuario   getUsuario()         { return usuario; }
	public String    getNombre()          { return nombre; }
	public String    getApellidos()       { return apellidos; }
	public String    getDni()             { return dni; }
	public String    getTelefono()        { return telefono; }
	public String    getCuentaCorriente() { return cuentaCorriente; }
	public Categoria getCategoria()       { return categoria; }
	
	public String getRol() {
		if (getCategoria() == Categoria.ADMINISTRADOR) {
			return ROL_ADMINISTRADOR;
		}
		else if (getCategoria() == Categoria.JEFE_SECCION) {
			return ROL_JEFESECCION;
		}
		else if (getCategoria() == Categoria.JEFE_TALLER) {
			return ROL_JEFETALLER;
		}
		else if (getCategoria() == Categoria.MECANICO) {
			return ROL_MECANICO;
		}
		
		return "DESCONOCIDO";
	}

	public
	void setUsuario(Usuario usuario) {
		this.usuario = usuario;
	}

	public
	void setNombre(String nombre) {
		this.nombre = nombre;
	}

	public
	void setApellidos(String apellidos) {
		this.apellidos = apellidos;
	}

	public
	void setDni(String dni) {
		this.dni = dni;
	}

	public
	void setTelefono(String telefono) {
		this.telefono = telefono;
	}

	public
	void setCuentaCorriente(String cuentaCorriente) {
		this.cuentaCorriente = cuentaCorriente;
	}

	public
	void setCategoria(Categoria categoria) {
		this.categoria = categoria;
	}

	/**
	 * Permite actualizar los datos de un empleado con los de otro que se pasa
	 * como parámetro
	 * 
	 * @param nuevosDatos
	 * @throws SQLException
	 */
	public void actualizar(Empleado nuevosDatos) throws SQLException {
		// TODO: Quizá introducir controles aquí
		setCategoria(nuevosDatos.getCategoria());
		setNombre(nuevosDatos.getNombre());
		setApellidos(nuevosDatos.getApellidos());
		setDni(nuevosDatos.getDni());
		setTelefono(nuevosDatos.getTelefono());
		setCuentaCorriente(nuevosDatos.getCuentaCorriente());
		
		update();
	}
	
	@Override
	public String toString() {
		return getNombre() + "(" + getCategoria().getDescriptor() + ")";
	}
	
	public String getApellidosYNombre() {
		return String.format("%s, %s", getApellidos(), getNombre());
	}
}